﻿using Neo4jClient;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WinFormsApp1
{
    /// <summary>
    /// 这是整个数据的知识图谱
    /// </summary>
    public class KnowlgeMap
    {
        public List<KnowlgeMapResult> results = new List<KnowlgeMapResult>();

        public void AddEntity(CommonEntity item)
        {
            results[0].data[0].graph.Add(item);
        }

        public void Initialize()
        {
            results.Add(new KnowlgeMapResult());
            results[0].Initialize();
        }

        #region 2-1 从文件构建
        internal static KnowlgeMap FromFile(string fileName)
        {
            var str = File.ReadAllText(fileName);
            return JsonConvert.DeserializeObject<KnowlgeMap>(str);
        }
        #endregion

        #region 2-2 从数据库构建
        internal static KnowlgeMap FromDB<T,T2>(BoltGraphClient client,string tableName)
        {
            Neo4JTableReader reader = new Neo4JTableReader()
            {
                TableName = tableName,
                Client = client
            };
            var dt = reader.GetRelationsAsGraphItem<T,T2>();
            KnowlgeMap knowlge = new KnowlgeMap();
            knowlge.Initialize();
            knowlge.results[0].data[0].graph = dt;
            return knowlge;
        }
        #endregion

        #region 3-1 构建索引
        public void BuildIndex()
        {
            results[0].BuildIndex();
        } 
        #endregion

        internal CommonRelation AddRelation(CommonEntity m_selectEntity1, CommonEntity m_selectEntity2, string text)
        {
            var r = new CommonRelation()
            {
                id = Guid.NewGuid().ToString(),
                startNode = m_selectEntity1.id,
                endNode = m_selectEntity2.id,
                type = text
            };
            foreach(var item in results[0].data[0].graph.relationships)
            {
                if (item.startNode == m_selectEntity1.id && item.endNode == m_selectEntity2.id)
                {
                    item.type = text;
                    return item;
                }
            }
            results[0].data[0].graph.relationships.Add(r);
            return r;
        }

        internal CommonEntity GetNodeById(string startNode)
        {
            return results[0].data[0].graph.GetNodeById(startNode);
        }

        internal List<CommonEntity> GetNodes()
        {
            return results[0].data[0].graph.nodes;
        }
        internal List<CommonRelation> GetRelationships()
        {
            return results[0].data[0].graph.relationships;
        }
        internal List<string> GetGroups()
        {
            var nodes = this.GetNodes();
            List<string> groups = new List<string>();
            foreach (var node in nodes)
            {
                var g = node.GetGroup();
                if (g != null)
                    groups.Add(g);
            }
            var g2 = groups.Distinct<string>().ToList();
            g2.Sort();
            return g2;
        }

        internal void DeleteRelation(CommonRelation? commonRelation)
        {
            results[0].data[0].graph.relationships.Remove(commonRelation);
        }

        
    }
    public class KnowlgeMapResult
    {
        public List<string> columns = new List<string>();
        public List<graphGroup> data = new List<graphGroup>();

        internal void BuildIndex()
        {
            data[0].graph.BuildIndex();
        }

        internal void Initialize()
        {
            columns.Add("Sd231");
            columns.Add("Sd232");
            data.Add(new graphGroup());
        }
    }
    public class graphGroup
    {
        public graphItem graph = new graphItem();
    }
    public class graphItem
    {
        public List<CommonEntity> nodes { get; set; } = new List<CommonEntity>();
        private Dictionary<string,CommonEntity> idToNodes = new Dictionary<string, CommonEntity>();
        public List<CommonRelation> relationships { get; set; } = new List<CommonRelation>();

        /// <summary>
        /// 构建id和实体之间的关系
        /// </summary>
        public void BuildIndex()
        {
            idToNodes.Clear();
            foreach (var node in nodes)
            {
                idToNodes.Add(node.id, node);
            }
        }
        public CommonEntity GetNodeById(string id)
        {
            return idToNodes[id];
        }
        internal void Add(CommonEntity item)
        {
            nodes.Add(item);
            idToNodes.Add(item.id, item);
        }
        internal void Add<T,T2>(T startNode, T endNode,T2 relationNode)
        {
            var startNode1 = (startNode as ICommonEntityConvertable).ToCommonEntity();
            var endNode1 = (endNode as ICommonEntityConvertable).ToCommonEntity();
            if (idToNodes.ContainsKey(startNode1.id) == false)
            {
                nodes.Add(startNode1);
                idToNodes.Add(startNode1.id, startNode1);
            }
            if (idToNodes.ContainsKey(endNode1.id) == false)
            {
                nodes.Add(endNode1);
                idToNodes.Add(endNode1.id, endNode1);
            }
            var cr = relationNode as CommonRelation;
            cr.startNode = startNode1.id;
            cr.endNode = endNode1.id;
            relationships.Add(cr);
        }
    }
}
